﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using UpdateManager.UserControls;
using System.Xml.Linq;
using UpdateManager.UserControls.Event;
using System.Threading;
using System.Diagnostics;

namespace UpdateManager {
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window {

        /// <summary>
        /// 提供更新的程序列表
        /// </summary>
        private List<UpdateItem> items = new List<UpdateItem>();
        /// <summary>
        /// 下载管理器
        /// </summary>
        private DownloadManager downloadManager = null;
        /// <summary>
        /// 下载项字典
        /// </summary>
        private Dictionary<string, UpdateItem> dicDownload = new Dictionary<string, UpdateItem>();
        /// <summary>
        /// 下载状态字典
        /// </summary>
        private Dictionary<string, bool> dicDownloadStatus = new Dictionary<string, bool>();
        /// <summary>
        /// 正在下载项
        /// </summary>
        private UpdateItem downloadingItem = null;
        /// <summary>
        /// 用于管理下载的线程
        /// </summary>
        private Thread threadDown = null;
        /// <summary>
        /// 本地配置信息
        /// </summary>
        private LocalAssemblyInfo localAssembly = null;
        /// <summary>
        /// 配置管理类
        /// </summary>
        private AssemblyManager assemblyManager = null;

        private Thread threadRemote = null;

        public MainWindow() {
            InitializeComponent();

            //初始化下载管理对象
            this.downloadManager = new DownloadManager();
            this.downloadManager.SaveFolder = "Updata";
            this.downloadManager.DownloadProgress += new EventHandler<ProgressEventArgs>(downloadManager_OnProgress);
            this.downloadManager.DownloadComplete += new EventHandler<EventArgs>(downloadManager_OnComplete);
            this.downloadManager.DownloadError += new EventHandler<ErrorEventArgs>(downloadManager_OnError);

            this.assemblyManager =  new AssemblyManager();

            this.threadRemote = new Thread(OnRemote);
            this.threadRemote.IsBackground = true;
            this.threadRemote.Start();

            

            //初始化下载任务管理线程
            this.threadDown = new Thread(OnDownload);
            threadDown.IsBackground = true;
            this.threadDown.Start();
        }

        

        /// <summary>
        /// 下载值守线程
        /// </summary>
        private void OnDownload() {
            while (true) {
                //获取没有在下载的项
                List<string> keys = this.dicDownloadStatus.Where(s => s.Value == false).Select(s => s.Key).ToList();

                //判断是否有没在下载的项
                if (keys != null && keys.Count > 0 && !this.downloadManager.IsDownloading) {
                    this.downloadingItem = this.dicDownload[keys[0]];
                    if (this.downloadingItem.IsDownloading) {
                        this.downloadManager.DownloadUrl = this.downloadingItem.AssemblyItem.UpdateUrl;
                        this.dicDownloadStatus[keys[0]] = true;
                        this.downloadManager.DoStart();
                    }
                }

                Thread.Sleep(500);
            }
        }

        private void downloadManager_OnError(object sender, ErrorEventArgs e) {
            //throw new NotImplementedException();
        }
        private void downloadManager_OnComplete(object sender, EventArgs e) {
            downloadingItem.Dispatcher.Invoke(new Action<EventArgs>(OnComplete), e);
        }
        private void downloadManager_OnProgress(object sender, ProgressEventArgs e) {
            downloadingItem.Dispatcher.Invoke(new Action<ProgressEventArgs>(OnProgress), e);
        }
        
        private void OnProgress(ProgressEventArgs e) {
            Windows7Taskbar.Taskbar.SetProgressValue(
                new System.Windows.Interop.WindowInteropHelper(this).Handle, (ulong)e.Progress, 100);

            downloadingItem.progressBar1.Value = e.Progress;
            downloadingItem.txtSpead.Text = "正在下载("+ e.Spead + ")";
        }

        private void OnComplete(EventArgs e) {
            Windows7Taskbar.Taskbar.SetProgressState(new System.Windows.Interop.WindowInteropHelper(this).Handle,
                Windows7Taskbar.Taskbar.ThumbnailProgressState.NoProgress);
            downloadingItem.progressBar1.Value = 100;
            downloadingItem.txtSpead.Text = "下载完成，正在安装。";
            downloadingItem.imgStart.Visibility = System.Windows.Visibility.Hidden;
            downloadingItem.imgStop.Visibility = System.Windows.Visibility.Hidden;

            string err = String.Empty;

            if (this.downloadingItem.AssemblyItem.Type == AssemblyType.Plugin) {
                Zip.UnZipFile(System.IO.Path.Combine("Updata",
                    DownloadManager.GetFileName(this.downloadingItem.AssemblyItem.UpdateUrl)), "Plugins", out err);
            } else {
                Zip.UnZipFile(System.IO.Path.Combine("Updata",
                    DownloadManager.GetFileName(this.downloadingItem.AssemblyItem.UpdateUrl)), ".", out err);
            }

            if (!String.IsNullOrEmpty(err)) {
                MessageBox.Show("无法复制文件, 当前文件正在被使用, 请关闭相关应用程序再试!" +
                    "\r\n或手动解压Update文件夹中的文件到应用程序文件夹", "出错", MessageBoxButton.OK);

                downloadingItem.txtSpead.Text = "安装出错。";
            } else {
                downloadingItem.txtSpead.Text = "安装完成。";

                if (this.localAssembly.AssemblyItems.Keys.Count(s => s == this.downloadingItem.AssemblyItem.AssemblyName) > 0) {
                    this.localAssembly.AssemblyItems[this.downloadingItem.AssemblyItem.AssemblyName].Version = this.downloadingItem.AssemblyItem.Version;
                } else {
                    this.localAssembly.AssemblyItems.Add(this.downloadingItem.AssemblyItem.AssemblyName,
                        new LocalAssemblyItemInfo() { IsTip = true, Version = this.downloadingItem.AssemblyItem.Version });
                }

                this.assemblyManager.ModifyLocalAssembly(this.localAssembly);
            }

            if (this.dicDownload.Keys.Contains(this.downloadingItem.AssemblyItem.AssemblyName)) {
                //移除正在下载的内容
                this.dicDownload.Remove(this.downloadingItem.AssemblyItem.AssemblyName);
                this.dicDownloadStatus.Remove(this.downloadingItem.AssemblyItem.AssemblyName);
            }
            this.downloadingItem = null;
        }

        #region UpdateItemg事件方法

        /// <summary>
        /// UpdateItem控件下载停止事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ui_OnStopDownload(object sender, UserControls.Event.DownloadEventArgs e) {
            //获取下载项
            UpdateItem item = (UpdateItem)sender;

            if (this.dicDownload.Keys.Contains(item.AssemblyItem.AssemblyName)) {
                //移除正在下载的内容
                this.dicDownload.Remove(item.AssemblyItem.AssemblyName);
                this.dicDownloadStatus.Remove(item.AssemblyItem.AssemblyName);
            }

            //重置下载项
            item.Reset();
            Windows7Taskbar.Taskbar.SetProgressState(new System.Windows.Interop.WindowInteropHelper(this).Handle,
                Windows7Taskbar.Taskbar.ThumbnailProgressState.NoProgress);

            if (this.downloadingItem != null && 
                this.downloadingItem.AssemblyItem.AssemblyName == item.AssemblyItem.AssemblyName) {
                
                this.downloadManager.DoStop();
            }
        }

        /// <summary>
        /// UpdateItem控件下载暂停事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ui_OnPauseDownload(object sender, UserControls.Event.DownloadEventArgs e) {
            //获取下载项
            UpdateItem item = (UpdateItem)sender;

            if (this.downloadingItem != null && this.downloadingItem.AssemblyItem.AssemblyName == item.AssemblyItem.AssemblyName) {
                this.downloadManager.DoPause();
            }
            if (this.dicDownload.Keys.Contains(item.AssemblyItem.AssemblyName)) {
                //移除正在下载的内容
                this.dicDownload.Remove(item.AssemblyItem.AssemblyName);
                this.dicDownloadStatus.Remove(item.AssemblyItem.AssemblyName);
            }
        }

        /// <summary>
        /// UpdateItem控件下载开始事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ui_OnStartDownload(object sender, UserControls.Event.DownloadEventArgs e) {
            //获取下载项
            UpdateItem item = (UpdateItem)sender;

            //将点击下载的项添加到下载列表中
            if (!this.dicDownload.Keys.Contains(item.AssemblyItem.AssemblyName)) {
                this.dicDownload.Add(item.AssemblyItem.AssemblyName, item);
                this.dicDownloadStatus.Add(item.AssemblyItem.AssemblyName, false);
            }
        }
        /// <summary>
        /// UpdateItem控件选中事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ui_OnCheckedChange(object sender, UserControls.Event.CheckedChangeEventArgs e) {
            //获取选中个数
            int count = items.Count(s => s.IsChecked);
            
            if (count == 0) { //没有选中项
                this.chkSelectAll.IsChecked = false;
                this.btnDownload.IsEnabled = false;
            } else if (count == this.items.Count(s => s.chkSelect.IsEnabled)) { //全部选中
                this.chkSelectAll.IsChecked = true;
                this.btnDownload.IsEnabled = true;
            } else { //部分选中
                this.chkSelectAll.IsChecked = null;
                this.btnDownload.IsEnabled = true;
            }
        }

        /// <summary>
        /// UpdateItem不提示单击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ui_OnNotTip(object sender, EventArgs e) {
            //获取下载项
            UpdateItem item = (UpdateItem)sender;

            if (this.localAssembly.AssemblyItems.Keys.Count(s => s == item.AssemblyItem.AssemblyName) > 0) {
                this.localAssembly.AssemblyItems[item.AssemblyItem.AssemblyName].IsTip = item.AssemblyItem.IsTip;
            } else {
                this.localAssembly.AssemblyItems.Add(item.AssemblyItem.AssemblyName,
                    new LocalAssemblyItemInfo() { IsTip = item.AssemblyItem.IsTip, Version = "" });
            }

            this.assemblyManager.ModifyLocalAssembly(this.localAssembly);
        }

        #endregion

        #region 界面控件事件方法

        /// <summary>
        /// 下载选中项按钮单击事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDownload_Click(object sender, RoutedEventArgs e) {
            //遍历
            foreach (UpdateItem item in this.items) {
                if (item.chkSelect.IsChecked.HasValue && item.chkSelect.IsChecked.Value) {
                    if (!this.dicDownload.Keys.Contains(item.AssemblyItem.AssemblyName)) {
                        this.dicDownload.Add(item.AssemblyItem.AssemblyName, item);
                        this.dicDownloadStatus.Add(item.AssemblyItem.AssemblyName, false);

                        item.DoDownload();
                    }
                }
            }
        }

        /// <summary>
        /// 全选框选中事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkSelectAll_Checked(object sender, RoutedEventArgs e) {
            //遍历
            foreach (UpdateItem item in this.items) {
                if (item.chkSelect.IsEnabled) {
                    item.chkSelect.IsChecked = true;
                }
            }
        }

        /// <summary>
        /// 全选框取消选中事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkSelectAll_Unchecked(object sender, RoutedEventArgs e) {
            //遍历
            foreach (UpdateItem item in this.items) {
                if (item.chkSelect.IsEnabled) {
                    item.chkSelect.IsChecked = false;
                }
            }
        }

        #endregion

        public void OnRemote() {
            //获取本地程集信息
            this.localAssembly = this.assemblyManager.GetLocalAssembly();
            //获取程序集信息
            AssemblyInfo assembly = this.assemblyManager.GetAssembly(this.localAssembly);

            this.Dispatcher.Invoke(new Action<AssemblyInfo>(RemoteOver), assembly);
        }

        public void RemoteOver(AssemblyInfo assembly) {
            //获取程序数量
            int countMainSoft = assembly.AssemblyItems.Count(s => s.Type == AssemblyType.MainSoftware);
            int countPlugin = assembly.AssemblyItems.Count(s => s.Type == AssemblyType.Plugin);
            //赋值可下载的程序数量
            this.countMainSoft.Text = countMainSoft.ToString();
            this.countPlungin.Text = countPlugin.ToString();

            //声明用来计算窗体位置的循环变量
            int i = 0;

            //添加主程序
            if (countMainSoft > 0) {
                ItemTitle title = new ItemTitle(countMainSoft, AssemblyType.MainSoftware);
                title.Margin = new Thickness(0, 0, 0, 0);
                title.Height = 30;
                title.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                this.grItem.Children.Add(title);

                var mainSoftware = assembly.AssemblyItems.Where(s => s.Type == AssemblyType.MainSoftware).ToList();
                foreach (AssemblyItemInfo item in mainSoftware) {
                    UpdateItem ui = new UpdateItem();
                    ui.AssemblyItem = item;
                    ui.Height = 60;
                    ui.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                    ui.Margin = new Thickness(0, 30 + 60 * i++, 0, 0);
                    ui.OnCheckedChange += new EventHandler<CheckedChangeEventArgs>(ui_OnCheckedChange);
                    ui.OnStartDownload += new EventHandler<DownloadEventArgs>(ui_OnStartDownload);
                    ui.OnPauseDownload += new EventHandler<DownloadEventArgs>(ui_OnPauseDownload);
                    ui.OnStopDownload += new EventHandler<DownloadEventArgs>(ui_OnStopDownload);
                    ui.OnNotTip += new EventHandler<EventArgs>(ui_OnNotTip);
                    items.Add(ui);
                    this.grItem.Children.Add(ui);
                }
            }
            //添加插件
            if (countPlugin > 0) {
                ItemTitle title = new ItemTitle(countPlugin, AssemblyType.Plugin);
                title.Margin = new Thickness(0, 60 * i + 30 * (countMainSoft > 0 ? 1 : 0), 0, 0);
                title.Height = 30;
                title.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                this.grItem.Children.Add(title);

                var plugins = assembly.AssemblyItems.Where(s => s.Type == AssemblyType.Plugin).ToList();
                foreach (AssemblyItemInfo item in plugins) {
                    UpdateItem ui = new UpdateItem();
                    ui.AssemblyItem = item;
                    ui.Height = 60;
                    ui.VerticalAlignment = System.Windows.VerticalAlignment.Top;
                    ui.Margin = new Thickness(0, 30 * (countMainSoft > 0 ? 2 : 1) + 60 * i++, 0, 0);
                    ui.OnCheckedChange += new EventHandler<CheckedChangeEventArgs>(ui_OnCheckedChange);
                    ui.OnStartDownload += new EventHandler<DownloadEventArgs>(ui_OnStartDownload);
                    ui.OnPauseDownload += new EventHandler<DownloadEventArgs>(ui_OnPauseDownload);
                    ui.OnStopDownload += new EventHandler<DownloadEventArgs>(ui_OnStopDownload);
                    items.Add(ui);
                    this.grItem.Children.Add(ui);
                }
            }

            if (this.items.Count(s => s.chkSelect.IsEnabled) > 0) {
                this.chkSelectAll.IsEnabled = true;
            } else {
                this.chkSelectAll.IsEnabled = false;
            }
        }

        private void Window_Closed(object sender, EventArgs e) {
            //判断本地的更新配置是否设置了重新启动主程序,并且主程序路径不为空
            if (!String.IsNullOrEmpty(this.localAssembly.AppName) && this.localAssembly.AutoStart) {
                //初始化进程对象
                Process ps = new Process();
                //赋值进程启动的文件名属性
                ps.StartInfo.FileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, this.localAssembly.AppName);
                //启动进程
                ps.Start();

                //清理对象
                ps.Dispose();
                ps = null;
            }
        }
    }
}
